package com.only4play.practice.message.core.events;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.only4play.codegen.support.exception.BusinessException;
import com.only4play.practice.common.constants.MessageConstants;
import com.only4play.practice.common.enums.MessageErrorCode;
import com.only4play.practice.common.enums.MsgTypeEnum;
import com.only4play.practice.common.enums.NoticeType;
import com.only4play.practice.common.properties.MessageProperties;
import com.only4play.practice.extension.executor.ServiceExecutor;
import com.only4play.practice.message.core.checker.CheckContext;
import com.only4play.practice.message.core.checker.SendIntervalChecker;
import com.only4play.practice.message.core.checker.SendMaxTimesChecker;
import com.only4play.practice.message.core.domain.model.SmsSendModel;
import com.only4play.practice.message.core.entity.MessageRecord;
import com.only4play.practice.message.core.service.ISmsSendService;
import com.only4play.practice.message.core.service.IVerifyRecordService;
import com.only4play.practice.message.model.creator.VerifyRecordCreator;
import com.only4play.practice.message.other.SmsBiz;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.matcher.ElementMatchers;
import org.apache.commons.collections4.MapUtils;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author mengdy
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MessageRecordEventProcessor {

   private final ServiceExecutor serviceExecutor;
   private final IVerifyRecordService verifyRecordService;
   private final MessageProperties messageProperties;
   /**
    * 如果是验证消息 单独存在验证记录里
    * @param createEvent
    */
   @EventListener
   public void handMessageRecordForSaveVerifyRecord(MessageRecordEvents.MessageRecordCreateEvent createEvent){
     MsgTypeEnum msgType = createEvent.getMessageRecord().getMsgType();
     // TODO 消息类型是验证码
     if(Objects.equals(MsgTypeEnum.VERIFY,msgType)){
       // 加上验证策略，可不可以发，发送间隔 ，发送策略属于什么问题？ 是否问题，是否问题用什么扩展， Matcher
       // 如果是验证码，存储验证记录
       CheckContext checkContext = new CheckContext();
       Map<String, Object> params = JSONObject.parseObject(createEvent.getMessageRecord().getParams());
       checkContext.setAccount(MapUtils.getString(params, MessageConstants.ACCOUNT));
       checkContext.setTemplateCode(createEvent.getMessageRecord().getTemplateCode());
       boolean checkResult = ElementMatchers.any()
           .and(new SendIntervalChecker())
           .and(new SendMaxTimesChecker())
               // TODO 可以在这里扩展要校验的 策略
           .matches(checkContext);
       if(!checkResult){
         log.error("发送频繁");
         throw new BusinessException(MessageErrorCode.MESSAGE_SEND_FAST);
       }
       VerifyRecordCreator creator = new VerifyRecordCreator();
       String verifyCode = RandomUtil.randomNumbers(messageProperties.getVerifyLength());
       creator.setAccount(MapUtils.getString(params, MessageConstants.ACCOUNT));
       creator.setTemplateCode(createEvent.getMessageRecord().getTemplateCode());
       creator.setContent(createEvent.getMessageRecord().getContent());
       creator.setVerifyCode(verifyCode);
       creator.setEndTime(Instant.now().plus(messageProperties.getSendInterval(), ChronoUnit.MINUTES).toEpochMilli());
       verifyRecordService.createVerifyRecord(creator);
       // TODO 通过mq异步发送
     }
   }

   /***
    * 处理钉钉消息  这里根据实际情况可以选择异步
    * @param createEvent
    */
   @EventListener
   public void handleMessageForDing(MessageRecordEvents.MessageRecordCreateEvent createEvent){
     NoticeType noticeType = createEvent.getMessageRecord().getNoticeType();
       MsgTypeEnum msgType = createEvent.getMessageRecord().getMsgType();
     // 生成消息记录之后是否真正发送消息，可以根据需要选择是否发送
     if(Objects.equals(NoticeType.DING_DING,noticeType) && Objects.equals(MsgTypeEnum.NOTICE,msgType)){

     }
   }

   /**
    * 处理短信消息，这里做成扩展点的方式
    * @param createEvent
    */
   @EventListener
   public void handleMessageForSms(MessageRecordEvents.MessageRecordCreateEvent createEvent){
     NoticeType noticeType = createEvent.getMessageRecord().getNoticeType();
     MsgTypeEnum msgType = createEvent.getMessageRecord().getMsgType();
     if(Objects.equals(NoticeType.SMS,noticeType) && Objects.equals(MsgTypeEnum.NOTICE,msgType)){
       MessageRecord messageRecord = createEvent.getMessageRecord();
       SmsSendModel ssm = new SmsSendModel();
         List<String> phoneList = new ArrayList<>();
         Map<String,Object> params = JSONObject.parseObject(messageRecord.getParams());
         phoneList.add(MapUtils.getString(params, MessageConstants.PHONE));
         ssm.setPhones(phoneList);
         ssm.setTemplateCode(messageRecord.getTemplateCode());
         ssm.setParams(params);
         // 设置参数
       Boolean sendResult = serviceExecutor.execute(ISmsSendService.class, SmsBiz.ALI, fun -> {
         return fun.sendSms(ssm);
       });
     }
   }

   /**
    * 处理邮件消息 ，邮件不经常变化，可以不做扩展点
    * @param createEvent
    */
   @EventListener
   public void handleMessageForEmail(MessageRecordEvents.MessageRecordCreateEvent createEvent){

   }


}
